package com.xyy.kingdeek3cloud.service.impl.pop;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kingdee.bos.webapi.entity.QueryParam;
import com.kingdee.bos.webapi.entity.RepoError;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.xyy.kingdeek3cloud.config.ComentCfg;
import com.xyy.kingdeek3cloud.entity.OrderUnitEntity;
import com.xyy.kingdeek3cloud.entity.SaveOrderDto;
import com.xyy.kingdeek3cloud.entity.erp.OrderTax;
import com.xyy.kingdeek3cloud.entity.erp.SaveCustomerDto;
import com.xyy.kingdeek3cloud.entity.pop.*;
import com.xyy.kingdeek3cloud.enums.K3FromEnum;
import com.xyy.kingdeek3cloud.enums.TaskEnum;
import com.xyy.kingdeek3cloud.helper.JdHelper;
import com.xyy.kingdeek3cloud.service.KingdeeService;
import com.xyy.kingdeek3cloud.service.PopApiService;
import com.xyy.kingdeek3cloud.service.PopService;
import com.xyy.kingdeek3cloud.utils.CfgUtils;
import com.xyy.kingdeek3cloud.utils.DateUtils;
import com.xyy.kingdeek3cloud.utils.IpUtils;
import com.xyy.kingdeek3cloud.utils.MD5Util;
import com.xyy.kingdeek3cloud.utils.http.RedirectUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.net.InetAddress;
import java.util.*;
import java.util.stream.Collectors;

import static com.xyy.kingdeek3cloud.utils.DateUtils.LONG_DATE_FORMAT_STR;
import static com.xyy.kingdeek3cloud.utils.DateUtils.SHORT_DATE_FORMAT_STR;

@Slf4j
@Service
public class PopServiceImpl implements PopService {

    private ComentCfg kingCfg = CfgUtils.getAppDefaultCfg();
    // @Value("${pop.orgId}")
    private String orgId = kingCfg.getOrgId();

    //@Value("${pop.appId}")
    private String appId = kingCfg.getAppId();

   // @Value("${pop.appSecret}")
    private String appSecret = kingCfg.getAppSecret();
    //@Value("${king.ckId}")
    private String ckId = kingCfg.getJdCkId();

    //@Value("${king.orderSaleId}")
    private String orderSaleId = kingCfg.getOrderSaleId();


    @Autowired
    private KingdeeService kingdeeService;

    @Autowired
    private PopApiService popApiService;


    //商品上报
    @Override
    public void syncProductFullToPop() {
        System.out.println(orgId);
        List<PopErpSkuForInsertDto> popErpSkuForInsertDtos = kingdeeService.JdProductInfo();
        //分批上报
        BatchRepOfProducts(popErpSkuForInsertDtos);
    }

    @Override
    public void syncOrderToMerchant() {
        List<SellerOrderInfoDto> sellerOrderInfoDtos = pullDataInfo(TaskEnum.ORDER_TOTAL.getTaskId(), SellerOrderInfoDto.class);
        if (sellerOrderInfoDtos.isEmpty()) {
            return;
        }
        log.info("#订单信息,jsonData: {}", JSON.toJSONString(sellerOrderInfoDtos));
        convertOrder(sellerOrderInfoDtos);

    }

    @Override
    public void syncNoneOpenCustomerToMerchant() {
        List<PlatformCustomerDto> platformCustomerDtos = pullDataInfo(TaskEnum.CLIENT_PUSH_DOWN.getTaskId(), PlatformCustomerDto.class);
        if (platformCustomerDtos.isEmpty()) {
            return;
        }
        log.info("#客户信息,jsonData: {}", JSON.toJSONString(platformCustomerDtos));
        for (PlatformCustomerDto platformCustomerDto : platformCustomerDtos) {
            K3CloudApi k3CloudApi = new K3CloudApi();
            SaveCustomerDto customerDto = new SaveCustomerDto();
            SaveCustomerDto.ModelDTO modelDTO = new SaveCustomerDto.ModelDTO();
            modelDTO.setFName(platformCustomerDto.getCustomerName());
            modelDTO.setFaddress(platformCustomerDto.getPickAddress());
            modelDTO.setFtaxregistercode(platformCustomerDto.getTaxpayerIdentity());
            modelDTO.setFinvoicebankname(platformCustomerDto.getRegisteredBank());
            modelDTO.setFinvoicetel(platformCustomerDto.getPickPhone());
            modelDTO.setFinvoicebankaccount(platformCustomerDto.getRegisteredBankAccount());
            modelDTO.setFinvoiceaddress(platformCustomerDto.getRegisteredAddress());
            modelDTO.setFtradingcurrid(new SaveCustomerDto.ModelDTO.FTRADINGCURRIDDTO("PRE001"));
            modelDTO.setFDescription("药帮忙接口自动生成");
            modelDTO.setFRegisterAddress(platformCustomerDto.getRegisteredAddress());
            modelDTO.setFrecconditionid(new SaveCustomerDto.ModelDTO.FRECCONDITIONIDDTO("SKTJ05_SYS"));
            customerDto.setModel(modelDTO);
            try {
                String save = k3CloudApi.save(K3FromEnum.BD_CUSTOMER.getName(), JSON.toJSONString(customerDto));
                RepoRet repoRet = JSON.parseObject(save, RepoRet.class);
                RepoError repoError = new RepoError();
                ArrayList<RepoError> errors = repoRet.getResult().getResponseStatus().getErrors();
                if (!errors.isEmpty()) {
                    repoError = errors.get(0);
                    log.info("#金蝶客户导入失败 CustomerError: {}", JSON.toJSONString(repoError));
                }
                if (repoRet.getResult().getResponseStatus().isIsSuccess() || "FName".equals(repoError.getFieldName())) {
                    extracted(platformCustomerDto);
                    log.info("客户信息回调成功: Data: {}", platformCustomerDto.getCustomerName());
                } else {
                    log.info("###客户信息回调失败 Data: {}", platformCustomerDto.getCustomerName());
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }


    }

    @Override
    public List<String> queryData(Integer taskId) {
        //查询出需要上传库存的品
        Map<String, Object> objectMap = buildPopTaskQueryParam(taskId, null);
        String body = RedirectUtil.doGetParam("https://h-api.ybm100.com/api/hackTask/queryTaskCondition", objectMap);
        ApiRPCResult apiRpcResult = JSON.parseObject(body, ApiRPCResult.class);
        if (apiRpcResult.getData() == null) {
            log.warn("#平台暂时无可用数据 apiRPCResult：{}", JSON.toJSONString(apiRpcResult));
            return new ArrayList<>();
        }
        ResultDto resultData = JSON.parseObject(JSON.toJSONString(apiRpcResult.getData()), ResultDto.class);
        String dataJson = resultData.getDataJson();
        QueryTaskData queryTaskData = JSON.parseObject(dataJson, QueryTaskData.class);
        return queryTaskData.getListQueryParam();
    }

    //客户回调
    private void extracted(@NotNull PlatformCustomerDto row) {
        List<SellerCustomerCallBackDto> callBackDtos = new ArrayList<>();
        SellerCustomerCallBackDto customerCallBackDto = new SellerCustomerCallBackDto();
        customerCallBackDto.setId(row.getId());
        customerCallBackDto.setNo(row.getCustomerName());
        customerCallBackDto.setResult(true);
        customerCallBackDto.setOrgId(orgId);
        callBackDtos.add(customerCallBackDto);
        //客户信息回调
        Map<String, Object> callTask = buildPopTaskQueryParam(10086, callBackDtos);
        RedirectUtil.doPostByJson("https://h-api.ybm100.com/api/hackTask/callbackForCustomerPullTask", JSON.toJSONString(callTask));
    }

    @Override
    public void syncProductStockToPop() {
        List<String> list = queryData(TaskEnum.PRODUCT_STOCK.getTaskId());
        if (list.isEmpty()) {
            log.info("当前没有需要同步库存商品!!!!");
            return;
        }
        List<String> collect = list.stream().map(m -> "'" + m + "'").collect(Collectors.toList());
        String join = String.join(",", collect);
        try {
            K3CloudApi k3CloudApi = new K3CloudApi();
            QueryParam queryParam = new QueryParam();
            queryParam.setFormId(K3FromEnum.STK_INVENTORY.getName());
            queryParam.setFieldKeys("FMaterialId.Fnumber,FBaseQty");
            queryParam.setFilterString("FStockId.fnumber in (" + ckId + ") and FMaterialId.Fnumber in (" + join + ")");
            List<List<Object>> lists = k3CloudApi.executeBillQuery(JSON.toJSONString(queryParam));
            List<PopErpSkuStockV2Dto> stockV2Dtos = JdHelper.convertToPopSkuStockDto(lists);
            Map<String, Object> objectMap = buildPopTaskQueryParam(TaskEnum.PRODUCT_STOCK.getTaskId(), stockV2Dtos);
            popApiService.pushDataInfo(objectMap);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public void syncCustomerToPop() {
        List<PopErpClientInfoDto> list = kingdeeService.JdClientInfo();
        Map<String, Object> objectMap = buildPopTaskQueryParam(TaskEnum.CLIENT_INFO.getTaskId(), list);
        popApiService.pushDataInfo(objectMap);
    }

    //已开单任务
    @Override
    public void syncCompletedToPop() {
        List<String> list = queryData(TaskEnum.ORDER_COMPLETE.getTaskId());
        if (list.isEmpty()) {
            log.info("暂无需要同步销售单!!!");
            return;
        }
        List<String> list1 = kingdeeService.QueryJdSalesOrder(list);
        if (list1.isEmpty()) {
            log.info("未查询到金蝶销售单信息 Data: {}", JSON.toJSONString(list));
            return;
        }
        List<Map<String, String>> orderNo = list1.stream().map(m -> {
            Map<String, String> map = new HashMap<>();
            map.put("order_no", m);
            return map;
        }).collect(Collectors.toList());
        Map<String, Object> objectMap = buildPopTaskQueryParam(TaskEnum.ORDER_COMPLETE.getTaskId(), orderNo);

        ApiRPCResult<Boolean> booleanApiRPCResult = popApiService.pushDataInfo(objectMap);
        if (booleanApiRPCResult == null || booleanApiRPCResult.isFail()) {
            log.warn("#分拣中任务上报失败  apiRPCResult: {},Data: {}", JSON.toJSONString(booleanApiRPCResult), JSON.toJSONString(orderNo));
            return;
        }
        log.info("#分拣中 上报成功订单 Data: {}", JSON.toJSONString(orderNo));
    }

    @Override
    public void syncOrderDeliveryDetails() {
        List<String> list = queryData(TaskEnum.ORDER_DELIVERY_DETAILE.getTaskId());
        if (list.isEmpty() || list.size() <= 0) {
            log.info("暂无需要同步出库单!!!");
            return;
        }
        List<SellerOrderDeliverDetailDto> sellerOrderDeliverDetailDtos = kingdeeService.QueryJdDeliveryOrder(list);
        if (sellerOrderDeliverDetailDtos.isEmpty() || sellerOrderDeliverDetailDtos.size() <= 0) {
            log.info("未查询到金蝶出库单信息 Data: {}", JSON.toJSONString(list));
            return;
        }
        Map<String, Object> objectMap = buildPopTaskQueryParam(TaskEnum.ORDER_DELIVERY_DETAILE.getTaskId(), sellerOrderDeliverDetailDtos);
        ApiRPCResult<Boolean> booleanApiRPCResult = popApiService.pushDataInfo(objectMap);
        if (booleanApiRPCResult == null || booleanApiRPCResult.isFail()) {
            log.warn("#出库单数据上报失败  apiRPCResult: {},Data: {}", JSON.toJSONString(booleanApiRPCResult), JSON.toJSONString(sellerOrderDeliverDetailDtos));
            return;
        }
        log.info("#出库单数据上报成功 Data: {}", JSON.toJSONString(sellerOrderDeliverDetailDtos));

    }

    /**
     * 心跳检测
     */
    @Override
    public void syncHeartBeatMonitor() {

        Map<String, Object> objectMap = buildPopTaskQueryParam(00000, null);
        Map<String, String> mapNew = new HashMap<>();
        for (Map.Entry<String, Object> map : objectMap.entrySet()) {
            mapNew.put(map.getKey(), map.getValue().toString());
        }
        log.info("集合 : {}", JSON.toJSONString(objectMap));
        String body = RedirectUtil.doPostByFrom("https://h-api.ybm100.com/api/hackTask/pushClientInfo", mapNew);
        ApiRPCResult<ResultDto> apiRPCResult = JSON.parseObject(body, ApiRPCResult.class);
        if (apiRPCResult == null || apiRPCResult.isFail()) {
            log.warn("#心跳失败  apiRPCResult: {}", JSON.toJSONString(apiRPCResult));
            return;
        }
        log.info("心跳成功!!!!!");

    }

    private void convertOrder(@NotNull List<SellerOrderInfoDto> sellerOrderInfoDtos) {
        for (SellerOrderInfoDto sellerOrderInfoDto : sellerOrderInfoDtos) {
            SaveOrderDto saveOrderDto = new SaveOrderDto();
            SaveOrderDto.ModelDTO orderInfo = new SaveOrderDto.ModelDTO();
            orderInfo.setFBillTypeID(new SaveOrderDto.ModelDTO.FBillTypeIDDTO("XSDD01_SYS"));
            orderInfo.setFBillNo(sellerOrderInfoDto.getOrderNo());
            orderInfo.setFDate(DateUtils.format(sellerOrderInfoDto.getOrderCreateTime(), SHORT_DATE_FORMAT_STR));
            orderInfo.setFSaleOrgId(new SaveOrderDto.ModelDTO.FSaleOrgIdDTO("100"));

            String venderCode = sellerOrderInfoDto.getVenderCode();
            if (venderCode == null) {
                log.info("订单未开户: {}", sellerOrderInfoDto.getOrderNo());
                continue;
            }
            orderInfo.setFCustId(new SaveOrderDto.ModelDTO.FCustIdDTO(venderCode));
            //销售员
            orderInfo.setFSalerId(new SaveOrderDto.ModelDTO.FSalerIdDTO(orderSaleId));
            orderInfo.setFLinkPhone(sellerOrderInfoDto.getPickPhone());
            orderInfo.setFLinkMan(sellerOrderInfoDto.getPickName());
            orderInfo.setFReceiveAddress(sellerOrderInfoDto.getPickAddress());
            //小药药单号
            orderInfo.setF_KBL_Text(sellerOrderInfoDto.getOrderNo());
            orderInfo.setFNote("药帮忙接口自动生成" + sellerOrderInfoDto.getRemark() != null ? sellerOrderInfoDto.getRemark() : "");
            //以上订单汇总
            //金蝶订单明细List
            List<SaveOrderDto.ModelDTO.FSaleOrderEntryDTO> list = new ArrayList<>();
            //POP订单明细List
            List<SellerOrderDetailDto> sellerOrderDetailLists = sellerOrderInfoDto.getSellerOrderDetailLists();
            for (SellerOrderDetailDto sellerOrderDetailList : sellerOrderDetailLists) {
                OrderUnitEntity orderUnitEntity = kingdeeService.JdOrderProductInfo(sellerOrderDetailList.getErpCode());
                if (orderUnitEntity == null) {
                    log.info("明细必填项未查询到数据! ErpCode: {}", sellerOrderDetailList.getErpCode());
                    continue;
                }
                OrderTax orderTax = kingdeeService.QueryBatchNumber(sellerOrderDetailList.getErpCode(), ckId);
                if (orderTax == null) {
                    log.info("批号查询失败! ErpCode: {}", sellerOrderDetailList.getErpCode());
                    continue;
                }
                SaveOrderDto.ModelDTO.FSaleOrderEntryDTO saveOrderDetail = new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO();
                saveOrderDetail.setFMaterialId(new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO.FMaterialIdDTO(sellerOrderDetailList.getErpCode()));
                //销售单位
                saveOrderDetail.setFUnitID(new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO.FUnitIDDTO(orderUnitEntity.getFUnitID()));
                saveOrderDetail.setFQty(sellerOrderDetailList.getPurchaseNumDecimal());
                //计价单位
                saveOrderDetail.setFPriceUnitId(new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO.FPriceUnitIdDTO(orderUnitEntity.getFPriceUnitId()));
                saveOrderDetail.setFDeliveryDate(DateUtils.format(sellerOrderInfoDto.getOrderCreateTime(), LONG_DATE_FORMAT_STR));
                saveOrderDetail.setFSettleOrgIds(new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO.FSettleOrgIdsDTO("100"));
                //预留类型
                saveOrderDetail.setFReserveType("1");
                //库存单位
                saveOrderDetail.setFStockUnitID(new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO.FStockUnitIDDTO(orderUnitEntity.getFStockUnitID()));
                saveOrderDetail.setFoutlmtunit("SAL");
                saveOrderDetail.setFTaxPrice(sellerOrderDetailList.getSkuPurchasePrice());
                saveOrderDetail.setF_KBL_Text1(String.valueOf(sellerOrderDetailList.getOrderDetailId()));
                //产地
                saveOrderDetail.setFAuxPropId(new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO.FAuxPropIdDTO(new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO.FAuxPropIdDTO.FAUXPROPID__FF100001DTO(orderTax.getProducingArea())));
                //批号
                saveOrderDetail.setFLot(new SaveOrderDto.ModelDTO.FSaleOrderEntryDTO.FLotDTO(orderTax.getBatch()));
                //生产日期
                saveOrderDetail.setFProduceDate(orderTax.getProdDate());
                //有效期
                saveOrderDetail.setFExpiryDate(orderTax.getValDate());
                list.add(saveOrderDetail);
            }
            if (list.isEmpty() || list.size() <= 0) {
                log.info("订单明细未导入: OrderNo: {}", sellerOrderInfoDto.getOrderNo());
                continue;
            }
            orderInfo.setFSaleOrderEntry(list);
            saveOrderDto.setModel(orderInfo);
            saveOrderDto.setIsVerifyBaseDataField(true);
            saveOrderDto.setIsAutoAdjustField(true);
            String jsonData = JSON.toJSONString(saveOrderDto);
            System.out.println(jsonData);
            K3CloudApi cloudApi = new K3CloudApi();
            try {
                String save = cloudApi.save(K3FromEnum.SAL_SALEORDER.getName(), jsonData);
                RepoRet repoRet = JSON.parseObject(save, RepoRet.class);
                RepoError repoError = new RepoError();
                ArrayList<RepoError> errors = repoRet.getResult().getResponseStatus().getErrors();
                if (!errors.isEmpty() && errors.size() > 0) {
                    repoError = errors.get(0);
                    log.info("#金蝶错误信息 orderError: {}", JSON.toJSONString(repoError));
                }
                if (repoRet.getResult().getResponseStatus().isIsSuccess() || "FBillNo".equals(repoError.getFieldName())) {
                    extracted(sellerOrderInfoDto);
                    log.info("订单回调成功: Data: {}", sellerOrderInfoDto.getOrderNo());
                } else {
                    log.info("###订单信息回调失败 Data: {}", sellerOrderInfoDto.getOrderNo());
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }
    }

    //订单回调
    private void extracted(@NotNull SellerOrderInfoDto sellerOrderInfoDto) {
        List<SellerOrderCallBackDto> orderCallBackDtos = new ArrayList<>();
        SellerOrderCallBackDto sellerOrderCallBackDto = new SellerOrderCallBackDto();
        sellerOrderCallBackDto.setOrderNo(sellerOrderInfoDto.getOrderNo());
        sellerOrderCallBackDto.setType(1);
        sellerOrderCallBackDto.setOrgId(orgId);
        sellerOrderCallBackDto.setResult(true);
        orderCallBackDtos.add(sellerOrderCallBackDto);
        //订单信息回调
        Map<String, Object> callTask = buildPopTaskQueryParam(10086, orderCallBackDtos);
        String body = RedirectUtil.doPostByJson("https://h-api.ybm100.com/api/hackTask/callbackForPullTask", JSON.toJSONString(callTask));
    }


    public <T> List<T> pullDataInfo(Integer taskId, Class<T> tClass) {
        //构建pop订单查询参数
        //构建查询pop参数
        Map<String, Object> objectMap = buildPopTaskQueryParam(taskId, null);
        String body = RedirectUtil.doGetParam("https://h-api.ybm100.com/api/hackTask/pullDataInfo", objectMap);
        ApiRPCResult<ResultDto> apiRPCResult = JSON.parseObject(body, ApiRPCResult.class);
        if (apiRPCResult == null || apiRPCResult.isFail()) {
            log.warn("#平台数据下推失败 taskQueryParam:{}, apiRPCResult：{}", JSONObject.toJSONString(objectMap), JSON.toJSONString(apiRPCResult));
            return new ArrayList<>();
        }
        if (apiRPCResult.getData() == null) {
            log.warn("#平台暂无可拉取数据 apiRPCResult：{}", JSON.toJSONString(apiRPCResult));
            return new ArrayList<>();
        }
        ResultDto resultData = JSON.parseObject(JSON.toJSONString(apiRPCResult.getData()), ResultDto.class);
        String dataJson = resultData.getDataJson();
        List<T> ts = JSON.parseArray(dataJson, tClass);
        return ts;
    }

    private <T> Map<String, Object> buildPopTaskQueryParam(Integer taskId, List<T> list) {


        TaskQueryParam taskQueryParam = new TaskQueryParam();
        taskQueryParam.setOrgId(orgId);
        taskQueryParam.setAppId(appId);
        if (taskId != null && taskId != 00000) {
            taskQueryParam.setTaskId(taskId);
        }
        if (taskId == 00000) {
            String ipAddress = "";
            InetAddress address = IpUtils.getLocalHostLANAddress();
            if (address != null) {
                ipAddress = address.getHostAddress();
            }
            taskQueryParam.setVersion("3.5");
            taskQueryParam.setJsonData(ipAddress);
        }
        if (!CollectionUtils.isEmpty(list)) {
            taskQueryParam.setJsonData(JSON.toJSONString(list));
        }
        Map<String, Object> popParamMap = JSON.parseObject(JSON.toJSONString(taskQueryParam)).getInnerMap();
        taskQueryParam.setSign(MD5Util.encrypt(popParamMap, appSecret));
        Map<String, Object> popParamMapNew = JSON.parseObject(JSON.toJSONString(taskQueryParam)).getInnerMap();
        return popParamMapNew;
    }


    //商品分批上报
    private void BatchRepOfProducts(@NotNull List<PopErpSkuForInsertDto> popErpSkuForInsertDtos) {
        int total = popErpSkuForInsertDtos.size();
        int pageSize = 1000;
        int startIndex = 0;
        while (startIndex < total) {
            int endIndex = Math.min(startIndex + pageSize, total);
            List<PopErpSkuForInsertDto> batch = popErpSkuForInsertDtos.subList(startIndex, endIndex);
            Map<String, Object> objectMap = buildPopTaskQueryParam(TaskEnum.PRODUCT_FULL.getTaskId(), batch);
            startIndex += pageSize;
        }
    }
}
